﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Crap4Net.CCParsers;
using Crap4Net.CoverageParsers;
using System.IO;
using System.Xml.Linq;

namespace Crap4Net.Specs.Features.BDDExample
{

    [TestClass]
    public class BDDExample
    {
        private XDocument _resultXml;

        [TestInitialize]
        public void cleanup()
        {
            try
            {
                Directory.Delete("Results", true);
            }
            catch (DirectoryNotFoundException)
            {
                //ignore
            }
            Directory.CreateDirectory("Results");
        }

        [TestMethod]
        public void CreateCrapReport_UsingNCover3CoverageData()
        {
            //given
            var ccReport = @"TestData\SimpleProject\CC\ncover3.nccov";
            var covReport = @"TestData\SimpleProject\Coverage\ncover3.nccov";
            var resultFileName = @"Results\Crap.xml";

            CrapAnalyzer.CCParser = new NCover3CCParser();
            CrapAnalyzer.CoverageParser = new NCover3CoverageParser();

            //when 
            var actual = CrapAnalyzer.CreateCrapReport(covReport, ccReport);
            IFormatter formatter = new XmlFormatter();
            var dir = Path.GetDirectoryName(resultFileName);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            formatter.FormatAndSaveToFile(actual, resultFileName);

            //then
            _resultXml = XDocument.Load(resultFileName);
            var methods = from method in _resultXml.Descendants()
                          where method.Name.LocalName == "Method"
                          select method;
            Assert.AreEqual(24, methods.Count());

            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "class2", ".ctor", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", ".ctor", "", "1"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "method2", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "method2", "System.Int32", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "method2", "System.Double", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "method2", "System.Single", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "method1", "", "2.16"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", ".cctor", "", "1"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "get_SomeProperty", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "set_SomeProperty", "System.Object", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "staticMethod", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "Class1", "GenericMethod<T>", "", "1"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "ClassWithAnonymousType", "StameMethod", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "dummyProject", "ClassWithAnonymousType", ".ctor", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", "StameMethod", "", "1"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "NameSpace1.NameSpace2", "ClassWithComplexNameSpace", ".ctor", "", "1"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "", "ClassWithNoNameSpace", "StameMethod", "", "2"));
            Assert.IsTrue(VerifyMethodIsInResult("DummyProject.dll", "", "ClassWithNoNameSpace", ".ctor", "", "2"));
        }


        private bool VerifyMethodIsInResult(string DLL, string NameSpace,
            string ClassName,
            string MethodName,
            string Args,
            string Crap)
        {
            var methods = from method in _resultXml.Descendants()
                          where method.Name.LocalName == "Method"
                          select method;

            var found = new List<XElement>();
            foreach (var item in methods)
            {
                if (Matching(DLL, NameSpace, ClassName, MethodName, Args, Crap, item))
                    return true;
            }
            return false;
        }

        private static bool Matching(string DLL,
            string NameSpace,
            string ClassName,
            string MethodName,
            string Args,
            string Crap,
            XElement result)
        {
            if (result.Attribute("Assembly").Value != DLL.Trim())
                return false;
            if (result.Attribute("NameSpace").Value != NameSpace.Trim())
                return false;
            if (result.Attribute("Type").Value != ClassName.Trim())
                return false;
            if (result.Attribute("Name").Value != MethodName.Trim())
                return false;
            if (result.Attribute("Args").Value != Args.Trim())
                return false;
            if (result.Attribute("Crap").Value != Crap.Trim())
                return false;
            return true;
        }
    }

}
